<template>
  <div id="article-comments" class="article-comments">
    <div class="user-submit">
      <h3>评论</h3>
      <div class="content">
        <HeadAvatar
          :width="40"
          :height="40"
          :img="
            userInfo
              ? userInfo.avatar || 'https://image.zdxblog.cn/picture/16849805191921684980519192.png'
              : require('~/assets/images/default.svg')
          "
        />
        <div class="right submit-comment-modal">
          <textarea
            id="commentInput"
            v-model="comment"
            placeholder="快来交流交流吧~"
          ></textarea>
          <div class="comment-image" v-show="imageInfo">
            <img :src="imageInfo" alt="">
            <i @click.stop="imageInfo = null" class="ri-close-circle-fill"></i>
          </div>
          <div class="bottom-operate">
            <div class="left-emoji-pic">
              <EmojiPicker :showText="false" @select="selectEmoji" />
              <a-upload
                name="file"
                action="https://image.zdxblog.cn/upload/uploadFile"
                :before-upload="beforeImageUpload"
                :showUploadList="false"
                @change="handleChange($event)"
              >
                <p class="select-pic">
                  <i class="ri-folder-image-line"></i>
                </p>
              </a-upload>
            </div>
            <a-button
              :disabled="!comment.replace(/\s/g, '')"
              type="primary"
              @click="submitComment(comment, imageInfo, articleDetail.userId, {})"
              >评论</a-button
            >
          </div>
        </div>
      </div>
    </div>
    <div v-if="commentList.length" class="comment-list">
      <h3>全部评论</h3>
      <div class="modal-list">
        <div v-for="item in commentList" :key="item.id" class="list">
          <HeadAvatar
            :width="40"
            :height="40"
            :to="`/user/${item.userId}`"
            :img="item.avatar"
          />
          <div class="right">
            <div class="user">
              <nuxt-link
                target="_blank"
                :to="`/user/${item.userId}`"
                class="nickname"
                >{{ item.nickname }}
                <span
                  v-if="item.userId === articleDetail.userId"
                  class="is-author"
                  >作者</span
                >
              </nuxt-link>
              <p class="job">{{ item.job || '' }}</p>
            </div>
            <div class="comment">
              <div>
                <p v-html="item.content"></p>
                <img v-if="item.commentImage" :src="item.commentImage" alt="">
              </div>
              <span
                v-if="item.isAuthor || userInfo.id === articleDetail.userId"
                @click="deleteComment(item.id)"
                class="delete"
                >删除</span
              >
            </div>
            <div class="dz-pl">
              <p :class="{ like: item.isLiker }" @click="isLikeComment(item)">
                <i class="ri-thumb-up-line"></i>
                <span v-if="item.likeCounts">{{ item.likeCounts }}</span>
              </p>
              <p @click="showCommentModal(item.id)">
                <i class="ri-message-ai-3-line"></i>
                <span v-if="item.replyCount">{{ item.replyCount }}</span>
              </p>
            </div>
            <div v-if="item.id === currentCommentId" class="reply-submit submit-comment-modal">
              <textarea
                :id="`${item.id}input`"
                v-model="item.replyNewComment"
                placeholder="快来交流交流吧~"
              ></textarea>
              <div class="comment-image" v-show="item.replyImage">
                <img :src="item.replyImage" alt="">
                <i @click.stop="item.replyImage = null" class="ri-close-circle-fill"></i>
              </div>
              <div class="bottom-operate">
                <div class="left-emoji-pic">
                  <EmojiPicker :showText="false" @select="selectEmoji($event, item)" />
                  <a-upload
                    name="file"
                    action="https://image.zdxblog.cn/upload/uploadFile"
                    :before-upload="beforeImageUpload"
                    :showUploadList="false"
                    @change="handleChange($event, item)"
                  >
                    <p class="select-pic">
                      <i class="ri-folder-image-line"></i>
                    </p>
                  </a-upload>
                </div>
                <a-button
                  :disabled="!item.replyNewComment.replace(/\s/g, '')"
                  type="primary"
                  @click="
                    submitComment(
                      item.replyNewComment,
                      item.replyImage,
                      item.userId,
                      {
                        topId: item.id,
                        replyId: item.id,
                        replyComment: item.content,
                      },
                      item
                    )
                  "
                  >评论</a-button
                >
              </div>
            </div>
            <div
              v-if="item.children && item.children.length"
              class="reply-comment"
            >
              <div
                v-for="itemName in item.children"
                :key="itemName.id"
                class="list"
              >
                <HeadAvatar
                  :width="28"
                  :height="28"
                  :to="`/user/${itemName.userId}`"
                  :img="itemName.avatar"
                />
                <div class="right">
                  <div class="user">
                    <nuxt-link
                      target="_blank"
                      :to="`/user/${itemName.userId}`"
                      class="nickname"
                      >{{ itemName.nickname }}
                      <span
                        v-if="itemName.userId === articleDetail.userId"
                        class="is-author"
                        >作者</span
                      >
                    </nuxt-link>
                    <p class="job">{{ itemName.job || '' }}</p>
                    <span class="aite" v-if="itemName.replyNickname">@</span>
                    <nuxt-link
                      target="_blank"
                      :to="`/user/${itemName.replyUserId}`"
                      class="nickname"
                      >{{ itemName.replyNickname }}</nuxt-link
                    >
                  </div>
                  <div class="comment">
                    <div>
                      <p v-html="itemName.content"></p>
                      <img v-if="itemName.commentImage" :src="itemName.commentImage" alt="">
                    </div>
                    <span
                      v-if="
                        itemName.isAuthor ||
                        userInfo.id === articleDetail.userId
                      "
                      class="delete"
                      @click="deleteComment(itemName.id)"
                      >删除</span
                    >
                  </div>
                  <div v-if="itemName.replyUserId" class="parent-comment">
                    <p>“<span v-html="itemName.replyComment"></span>”</p>
                  </div>
                  <div class="dz-pl">
                    <p
                      :class="{ like: itemName.isLiker }"
                      @click="isLikeComment(itemName)"
                    >
                      <i class="ri-thumb-up-line"></i>
                      <span v-if="itemName.likeCounts">{{ itemName.likeCounts }}</span>
                    </p>
                    <p @click="showCommentModal(itemName.id)">
                      <i class="ri-message-ai-3-line"></i>
                      <span v-if="itemName.replyCount">{{
                        itemName.replyCount
                      }}</span>
                    </p>
                  </div>
                  <div
                    v-if="itemName.id === currentCommentId"
                    class="reply-submit submit-comment-modal"
                  >
                    <textarea
                      :id="`${itemName.id}input`"
                      v-model="itemName.replyNewComment"
                      placeholder="快来交流交流吧~"
                    ></textarea>
                    <div class="comment-image" v-show="itemName.replyImage">
                      <img :src="itemName.replyImage" alt="">
                      <i @click.stop="itemName.replyImage = null" class="ri-close-circle-fill"></i>
                    </div>
                    <div class="bottom-operate">
                      <div class="left-emoji-pic">
                        <EmojiPicker :showText="false" @select="selectEmoji($event, itemName)" />
                        <a-upload
                          name="file"
                          action="https://image.zdxblog.cn/upload/uploadFile"
                          :before-upload="beforeImageUpload"
                          :showUploadList="false"
                          @change="handleChange($event, itemName)"
                        >
                          <p class="select-pic">
                            <i class="ri-folder-image-line"></i>
                          </p>
                        </a-upload>
                      </div>
                      <a-button
                        :disabled="!itemName.replyNewComment.replace(/\s/g, '')"
                        type="primary"
                        @click="
                          submitComment(
                            itemName.replyNewComment,
                            itemName.replyImage,
                            itemName.userId,
                            {
                              topId: item.id,
                              replyId: itemName.id,
                              replyComment: itemName.content,
                              replyNickname: itemName.nickname,
                              replyUserId: itemName.userId,
                            },
                            itemName
                          )
                        "
                        >评论</a-button
                      >
                    </div>
                  </div>
                </div>
                <div class="time">{{ cycleDate(itemName.createTime) }}</div>
              </div>
            </div>
          </div>
          <div class="time">{{ cycleDate(item.createTime) }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { cycleDate } from '~/util'
import EmojiPicker from '~/components/EmojiPicker'
import { getTargetParentNode } from '@/util'

export default {
  name: 'ArticleComment',
  components: { EmojiPicker },
  props: {
    articleDetail: {
      type: Object,
      default: () => {}
    }
  },
  data () {
    return {
      cycleDate,
      comment: '',
      commentList: [],
      currentCommentId: null,
      imageInfo: null
    }
  },

  computed: {
    ...mapState({
      userInfo: (state) => state.userInfo
    })
  },

  created () {
    this.findComments()
  },

  mounted () {
    document.querySelector('body').onclick = function (e) {
      if (getTargetParentNode(e.target, 'emoji-popover')) return
      const parentNode = getTargetParentNode(e.target, 'submit-comment-modal')
      const oldOpenFocusNodes = document.querySelectorAll('.open-focus')
      for (let i = 0; i < oldOpenFocusNodes.length; i++) {
        const node = oldOpenFocusNodes[i]
        if (!node.querySelector('textarea').value) {
          node.classList.remove('open-focus')
        }
      }
      if (parentNode) {
        parentNode.classList.add('open-focus')
      }
    }
  },

  methods: {
    /**
     * submit comment
     * @param { String } comment
     * @param { String } replyImage
     * @param { String } uid
     * @param { String } topId
     * @param { String } replyId
     * @param { String } replyComment
     * @param { String } replyNickname
     * @param { String } replyUserId
     */
    async submitComment (
      comment,
      replyImage,
      uid,
      { topId, replyId, replyComment, replyNickname, replyUserId },
      commentItem
    ) {
      if (!this.userInfo) {
        return this.$store.commit('UPDATE_LOGIN_VISIBLE', true)
      }
      try {
        const commentInfo = {
          articleId: this.articleDetail.id,
          uid,
          topId,
          replyId,
          replyComment,
          content: comment,
          replyNickname,
          commentImage: replyImage,
          replyUserId
        }
        await this.$axios.post('/gimishare/api/v1/article/comments/submit', commentInfo)
        this.findComments()
        this.currentCommentId = null
        this.$message.success('评论成功')
        if (commentItem) {
          commentItem.replyNewComment = ''
          commentItem.replyImage = null
        } else {
          this.comment = ''
          this.imageInfo = null
        }
        const oldOpenFocusNode = document.querySelector('.open-focus')
        oldOpenFocusNode && oldOpenFocusNode.classList.remove('open-focus')
      } catch (error) {
        console.log(error)
      }
    },

    /**
     * find article comments
     */
    async findComments () {
      try {
        const { data } = await this.$axios.get(
          `/gimishare/api/v1/article/comments?articleId=${this.articleDetail.id}`
        )
        this.treeStructure(data)
        this.commentList = data
      } catch (error) {
        console.log(error)
      }
    },

    /**
     * like comment
     * @params { String } commentItem
     */
    async isLikeComment (commentItem) {
      if (!this.userInfo) {
        return this.$store.commit('UPDATE_LOGIN_VISIBLE', true)
      }
      try {
        const API = commentItem.isLiker
          ? '/users/unagreecomment'
          : '/users/agreecomment'
        await this.$axios.get(
          `/gimishare/api/v1${API}?commentId=${commentItem.id}&itemType=1`
        )
        if (commentItem.isLiker) {
          commentItem.likeCounts -= 1
        } else {
          commentItem.likeCounts += 1
        }
        commentItem.isLiker = !commentItem.isLiker
      } catch (error) {
        console.log(error)
      }
    },

    /**
     * delete comment
     * @params { String } commentId
     */
    async deleteComment (commentId) {
      try {
        await this.$axios.get(`/gimishare/api/v1/article/comments/delete?id=${commentId}`)
        this.findComments()
      } catch (error) {
        console.log(error)
      }
    },

    /**
     * @parma { String } commentId
     */
    showCommentModal (commentId) {
      if (commentId === this.currentCommentId) {
        return (this.currentCommentId = null)
      }
      this.currentCommentId = commentId
    },

    /**
     * select emoji
     * @param { Object } emoji
     * @param { Object } commentItem
     */
    selectEmoji (emoji, commentItem) {
      const input = commentItem
        ? document.getElementById(`${commentItem.id}input`)
        : document.getElementById('commentInput')
      const startPos = input.selectionStart
      const endPos = input.selectionEnd
      const resultText =
        input.value.substring(0, startPos) +
        emoji.data +
        input.value.substring(endPos)
      input.value = resultText
      input.focus()
      input.selectionStart = startPos + emoji.data.length
      input.selectionEnd = startPos + emoji.data.length
      if (commentItem) {
        commentItem.replyNewComment = resultText
      } else {
        this.comment = resultText
      }
    },

    /**
     * package treestructure fileds
     * @param { Array } listTree
     */
    treeStructure (listTree) {
      for (let i = 0; i < listTree.length; i++) {
        listTree[i].replyNewComment = ''
        listTree[i].replyImage = null
        const regex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g // 匹配 Emoji 的正则表达式
        listTree[i].content = listTree[i].content.replace(regex, '<em>$&</em>') // 将 Emoji 替换为 [Emoji]
        if (listTree[i].children && listTree[i].children.length) {
          this.treeStructure(listTree[i].children)
        }
      }
    },

    beforeImageUpload (file) {
      const fileType = file.name
        .substring(file.name.lastIndexOf('.') + 1)
        .toLowerCase()
      if (!['jpeg', 'jpg', 'svg', 'gif', 'png', 'webp'].includes(fileType)) {
        this.$message.error('上传图片格式不正确')
        return false
      }
      const isLt5M = file.size / 1024 / 1024 < 5
      if (!isLt5M) {
        this.$message.error('上传图片大小不能超过 5MB!')
        return false
      }
      return true
    },

    handleChange (info, commentItem) {
      if (info.file.status === 'done') {
        if (commentItem) {
          commentItem.replyImage = info.file.response.data
        } else {
          this.imageInfo = info.file.response.data
        }
      }
      if (info.file.status === 'error') {
        this.$message.error('上传图片失败')
      }
    }
  },

  beforeDestroy () {
    document.querySelector('body').onclick = null
  }
}
</script>

<style scoped lang="less">
.article-comments {
  background: #fff;
  padding: 30px;
  margin-top: 12px;
  border-radius: 4px;
  .submit-comment-modal {
    position: relative;
    border: 1px solid transparent;
    border-radius: 4px;
    overflow: hidden;
    background: rgb(243, 242, 245);
    textarea {
      border: none;
      outline: none;
      width: 100%;
      border-radius: 4px;
      padding: 10px 12px;
      resize: none;
      color: #4c4c4c;
      transition: 0.2s;
      min-height: 60px;
      display: block;
      background: rgb(243, 242, 245);
    }
    .comment-image {
      margin: 0 0 6px 12px;
      position: relative;
      display: inline-block;
      img {
        width: 80px;
        height: 80px;
        display: block;
        object-fit: cover;
      }
      .ri-close-circle-fill {
        position: absolute;
        right: -8px;
        top: -12px;
        cursor: pointer;
        color: #999;
      }
    }
    .bottom-operate {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 10px 6px 12px;
      .left-emoji-pic {
        display: flex;
        align-items: center;
        ::v-deep .custom-emoji-picker {
          i {
            color: #878585;
            font-size: 21px;
          }
        }
        .select-pic {
          margin-left: 16px;
          cursor: pointer;
          i {
            font-size: 22px;
            color: #878585;
          }
        }
      }
    }
    &.open-focus {
      border-color: var(--primary-color);
      textarea {
        min-height: 130px;
        max-height: 300px;
      }
    }
  }

  .user-submit {
    h3 {
      color: #000;
      font-weight: bold;
      font-size: 17px;
    }
    .content {
      display: flex;
      margin-top: 20px;
      .right {
        flex: 1;
        width: 0;
        margin-left: 12px;
      }
    }
  }
  .comment-list {
    margin-top: 12px;
    h3 {
      color: #000;
      font-weight: bold;
      margin-bottom: 20px;
      font-size: 17px;
    }
    .modal-list {
      .list {
        display: flex;
        margin: 16px 0;
        position: relative;
        .right {
          flex: 1;
          width: 0;
          margin-left: 12px;
          .user {
            display: flex;
            .nickname {
              color: #4c4c4c;
              .is-author {
                padding: 2px 6px;
                background: #eaf2ff;
                font-size: 12px;
                color: var(--primary-color);
                border-radius: 4px;
              }
            }
            .job {
              color: #999;
              margin-left: 4px;
              font-size: 12px;
              position: relative;
              top: 2px;
            }
            .aite {
              padding: 0 6px;
              color: #999;
            }
          }
          .comment {
            padding: 6px 0;
            display: flex;
            & > div {
              flex: 1;
              width: 0;
              padding-right: 20px;
              p {
                color: #000;
                white-space: pre-wrap;
                line-height: 22px;
                ::v-deep em {
                  font-style: normal;
                  font-size: 16px;
                  & + em {
                    margin-left: 1px;
                  }
                }
              }
              img {
                display: block;
                max-width: 100px;
                margin-top: 6px;
              }
            }
            .delete {
              color: #d83030;
              font-size: 12px;
              cursor: pointer;
              font-weight: 600;
              letter-spacing: 1px;
              display: none;
            }
            &:hover {
              span {
                display: block;
              }
            }
          }
          .dz-pl {
            display: flex;
            p {
              margin-right: 16px;
              cursor: pointer;
              i {
                font-size: 16px;
              }
              &.like,
              &:hover {
                color: var(--primary-color);
              }
            }
          }
          .reply-submit {
            margin-top: 10px;
          }
          .reply-comment {
            .list {
              padding: 0;
              margin-top: 10px;
            }
            .parent-comment {
              border: 1px solid #e4e6eb;
              background: #f2f3f5;
              border-radius: 4px;
              padding: 5px 10px;
              margin-bottom: 6px;
              p {
                color: #8a919f;
                ::v-deep {
                  em {
                    font-style: normal;
                    font-size: 16px;
                    margin: 0 1px;
                  }
                }
              }
            }
          }
        }
        .time {
          color: #999;
          font-size: 12px;
          position: absolute;
          right: 0;
          top: 2px;
        }
      }
    }
  }
}
</style>
